from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework import serializers
from users.models import UserModel
from django_redis import get_redis_connection
import re
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    # 自定义序列化器，实现自定义载荷信息的添加
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        # 根据用户，获取token
        token['id'] = str(user.id)
        token['username'] = str(user.username)
        token['avatar'] = str(user.avatar)
        token['money'] = str(user.money)
        token['credit'] = str(user.credit)
        return token

class RegisterSerializer(serializers.ModelSerializer):
    re_password = serializers.CharField(required=True,write_only=True,min_length=6,max_length=16)
    sms_code = serializers.CharField(required=True,write_only=True,min_length=3,max_length=5)

    # 仅在序列化中使用，用于注册成功后，返回登录令牌 ；toekn  refresh
    token = serializers.CharField(read_only=True)
    refresh = serializers.CharField(read_only=True)

    class Meta():
        model = UserModel
        fields = ['mobile','password','token','refresh','re_password','sms_code']
        extra_kwargs = {
            "mobile":{
                "required":True,
                "write_only":True,
            },
            "password":{
                "required": True,
                "write_only": True,
                "min_length":6,
                "max_length":16
            }
        }
    def validate(self, attrs):
        # 自定义任意校验规则
        # 校验传递数据，是否满足业务需求
        mobile = attrs.get('mobile',None)
        # 判断手机号是否满足规则
        if not re.match(r'^1[3-9]\d{9}$',mobile):
            raise serializers.ValidationError(detail="手机号格式错误",code="mobile")
        print('-------手机号校验通过--------')

        # 校验两次密码是否相同
        password = attrs.get('password')
        re_password = attrs.get('re_password')

        if password != re_password:
            raise serializers.ValidationError(detail="两次密码不一致,请重新输入密码",code="password")

        print('-------密码校验通过,两次密码相同---------')

        # -------------------redis:短信验证码------------------
        # 验证码操作 稍后开发
        sms_code = attrs.get('sms_code')
        # 默认验证码是正确,redis中获取到数据类型,都是字节类型的
        redis = get_redis_connection('sms_code')
        # 获取手机号对应的验证码
        code = redis.get(f"sms_{mobile}")
        # redis中获取到数据类型,都是字节类型的
        print('redis中保存的短信验证码:', code)
        if code == None:
            raise serializers.ValidationError(detail="验证码已过期,请重新获取验证码",code="sms_code")
        # code.decode()是一个用于将编码后的字节序列解码为字符串的方法
        if code.decode() != sms_code:
            raise serializers.ValidationError(detail="验证码错误,请重新输入验证码",code="sms_code")
        redis.delete(f"sms_{mobile}")
        # -------------------redis:短信验证码------------------
        # 程序健壮性考虑
        # 判断一次用户是否存在
        try:
            UserModel.objects.get(mobile__exact=mobile)
            raise serializers.ValidationError(detail="用户已存在,请重新输入手机号",code="mobile")
        except UserModel.DoesNotExist:
            print('注册信息,不存在于数据,可以正常执行注册操作.所有数据校验通过')

        # 校验通过，删除不必要得字段
        attrs.pop('re_password')
        attrs.pop('sms_code')
        return attrs
    def create(self, validated_data):
        mobile = validated_data.get('mobile')
        password = validated_data.get('password')
        # 注册新用户，初始化用户信息
        userx = UserModel.objects.create_user(
            mobile = mobile,
            password= password,
            # 随机给默认用户名 ,根据需求随机生成  小伙子_KFDSKJLK_123
            username= mobile,
            money = 0.0,
            credit = 0,
            avatar = "avatar/2021/default.jpg"
        )
        # 返回数据
        # token   refresh
        print('------用户创建成功,手动签发token----------')
        # 手动签发token
        refresh = CustomTokenObtainPairSerializer.get_token(user=userx)

        userx.refresh = str(refresh)
        userx.token = str(refresh.access_token)

        return userx